package com.test;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.SurfaceHolder;

public class SocketCamera {

	private static final String LOG_TAG = "SocketCamera:";
	private CameraCapture capture;
	private SurfaceHolder surfaceHolder;
	private InputStream in;
	final private String TAG = "SocketCamera";

	private final boolean preserveAspectRatio = true;
	private final Paint paint = new Paint();

	private int width = 240;
	private int height = 320;
	private Rect bounds = new Rect(0, 0, width, height);
	private Socket socket;
	private FileDescriptor fd;

	SocketCamera(Socket socket, int width, int height) throws IOException {
		// Just used so that we can pass inputstream to getters and setters
		if (socket.isClosed()){
			Log.i(TAG, "SocketCamera passed socket is closed!");
		}
		this.socket = socket;
		this.in = socket.getInputStream();
		fd = ParcelFileDescriptor.fromSocket(socket).getFileDescriptor();

		/*
		Camera cam = Camera.open();
		cam.getParameters();

		Log.i(LOG_TAG, "SocketCamera width: "+width+", height: "+height);
		this.width = cam.getParameters().getPreviewSize().width;
		this.height = cam.getParameters().getPreviewSize().height;
		bounds = new Rect(0, 0, width, height);
		 */
	}

	/*
	static public SocketCamera open(Socket socket, int width, int height) throws IOException {
		Log.i("SocketCamera", "SocketCamera open()");
		if (socketCamera == null || socketCamera.socket.isClosed()) {
			Log.i("SocketCamera", "SocketCamera=null open()");
			socketCamera = new SocketCamera(socket, width, height);
		}

		Log.i(LOG_TAG, "Creating Socket Camera");
		return socketCamera;
	}
	 */
	public void startPreview() {
		Log.i(TAG, "SocketCamera startPreview");
		capture = new CameraCapture();
		capture.setCapturing(true);
		capture.start();
		Log.i(LOG_TAG, "Starting Socket Camera");

	}

	public void stopPreview() {
		Log.i(TAG, "SocketCamera stopPreview");
		if (capture!=null){
			capture.setCapturing(false);
			Log.i(LOG_TAG, "Stopping Socket Camera");
		}

	}

	public void setPreviewDisplay(SurfaceHolder surfaceHolder)
	throws IOException {
		this.surfaceHolder = surfaceHolder;
	}

	public void release() {
		Log.i(LOG_TAG, "Releasing Socket Camera parameters");
		capture.release();

	}

	private class CameraCapture extends Thread {
		Canvas c;
		private boolean capturing = false;

		public synchronized void setCapturing(boolean capturing) {
			Log.i(TAG, "CameraCapture set capturing: "+capturing);
			this.capturing = capturing;
		}
		public synchronized void release(){
			if(c != null){
				Log.i(TAG, "Surfaceholder unlock canvas");
				surfaceHolder.unlockCanvasAndPost(c);
			}
		}

		@Override
		public void run() {
			Log.i(TAG, "CameraCapture run()");

			//c = surfaceHolder.lockCanvas();
			while (capturing && 
					!socket.isClosed()
			) {

				c = null;
				Log.i(TAG, "CameraCapture Canvas = null");
				try {
					Log.i(TAG, "CameraCapture trying to lock surface");
					c = surfaceHolder.lockCanvas();
					Log.i(TAG, "CameraCapture locked surface");

					captureFrame();
					Log.i(TAG, "CameraCapture synching surfaceholder");

				} catch (Exception e) {
					e.printStackTrace();
				} finally {

					// do this in a finally so that if an exception is thrown
					// during the above, we don't leave the Surface in an
					// inconsistent state
					Log.i(TAG, "CameraCapture finally");
					//release();

				}
			}
			Log.i(LOG_TAG, "Socket Camera capture stopped");

		}

		public synchronized void captureFrame(){
			Log.i(TAG, "CameraCapture capture frame");
			if(capturing == true){
				try {
					Bitmap bitmap = BitmapFactory.decodeStream(in);
					//Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd);


					//InputStream FdInputstream = new FileInputStream(fd);
					//Bitmap bitmap = BitmapFactory.decodeStream(FdInputstream);


					if(bitmap == null){
						//indicates cannot decode from inputstream
						//System.out.println("Bitmap null");
					}
					else if(bounds == null){
						System.out.println("Bounds null");
					}
					// render it to canvas, scaling if necessary
					else if (
							bounds.right == bitmap.getWidth()
							&& bounds.bottom == bitmap.getHeight()) {
						Log.i(TAG, "CameraCapture draw bitmap bitmap, 0, 0, null");
						c.drawBitmap(bitmap, 0, 0, null);
					} else {
						Rect dest;
						if (preserveAspectRatio) {
							dest = new Rect(bounds);
							dest.bottom = bitmap.getHeight()
							* bounds.right / bitmap.getWidth();
							dest.offset(0,
									(bounds.bottom - dest.bottom) / 2);
						} else {
							dest = bounds;
						}
						if (c != null) {
							Log.i(TAG, "CameraCapture draw bitmap bitmap, null, dest, paint");
							c.drawBitmap(bitmap, null, dest, paint);
						}
					}

				} catch (RuntimeException e) {
					e.printStackTrace();
				}

			}
		}
	}

}
